import Vue from "vue";
import Component from "vue-class-component";
import { Observer } from "mobx-vue";
import "./imageClipper.scss";

@Observer
@Component({
  name: "CcuiImageClipper",
  props: {
    title: {
      type: String,
      default: ""
    },
    imgUrl: {
      type: String,
      default: ""
    },
    width: {
      type: Number,
      default: null
    },
    height: {
      type: Number,
      default: null
    },
    scale: {
      type: String,
      default: "1:1"
    },
    maxScale: {
      type: Number,
      default: null
    },
    isHead: {
      type: Boolean,
      default: false
    }
  }
})
export default class CcuiImageClipper extends Vue {
  img: any = null; //图片
  ctx: any = null; //下层画布
  pCtx: any = null; //上层画布
  originXDiff: any = 0; //裁剪canvas与原图canvas坐标原点上的差值
  originYDiff: any = 0;
  scaleArr: any = []; //传进来的比例 第一项是宽 第二项是高
  imgStartWidth: any = null; //下层画布初始化的宽
  imgStartHeight: any = null; //下层画布初始化的高
  imgX: any = null; //下层画布的x值
  imgY: any = null; //下层画布的y值
  imgCurrentWidth: any = null; //下层画布的宽
  imgCurrentHeight: any = null; //下层画布的高
  imgLoading: any = false;
  imgLoaded: any = false;
  loadImgQueue: any = []; //加载图片队列
  imgScale: any = 1; //图片缩放的比例
  pCanvasWidth: any = 0; //裁切部分canvas的宽高
  pCanvasHeight: any = 0;
  previewImg: any = ""; //预览的图片
  previewWidth: any = 0; //预览图片的宽
  previewHeight: any = 0; //预览图片的高
  overflowY: any = ""; //原来overflowY属性
  originalImgWidth: any = 0;//原图的宽
  originalImgHeight: any = 0;//原图的高
  //常量
  clipperSize: number = 350; //裁切部分的大小

  mounted() {
    setTimeout(() => {
      this.init();
    }, 10);
  }
  init() {
    let vm: any = this;
    vm.scaleArr = vm.scale.split(":");
    vm.scaleArr = [Number(vm.scaleArr[0]), Number(vm.scaleArr[1])];
    vm.loadImgQueue.push(vm.imgUrl);
    vm.overflowY = document.documentElement.style.overflowY;
    document.documentElement.style.overflowY = "hidden"; //禁止滚动条滚动
    vm.initCanvas();
    vm.loadImg();
    vm.initPreview();
    vm.scollEvent();
    vm.dragEvent();
  }
  //初始化画布
  initCanvas() {
    let vm: any = this,
      canvas: any = vm.$refs.canvas,
      pCanvas: any = vm.$refs.pCanvas;
    let pCanvasSize: any = vm.clipperSize * 0.8;
    vm.ctx = canvas.getContext("2d");
    vm.pCtx = pCanvas.getContext("2d");
    canvas.width = vm.clipperSize;
    canvas.height = vm.clipperSize;
    if (vm.scaleArr[0] <= vm.scaleArr[1]) {
      //传进来的长宽比 宽<高
      vm.pCanvasWidth = (vm.scaleArr[0] / vm.scaleArr[1]) * pCanvasSize;
      vm.pCanvasHeight = pCanvasSize;
    } else {
      //传进来的长宽比 宽>高
      vm.pCanvasWidth = pCanvasSize;
      vm.pCanvasHeight = (pCanvasSize * vm.scaleArr[1]) / vm.scaleArr[0];
    }
    pCanvas.width = vm.pCanvasWidth;
    pCanvas.height = vm.pCanvasHeight;
    //设置外层的宽高，让其与canvas一致
    let canvasCon: any = vm.$refs.canvasCon;
    canvasCon.style.width = vm.pCanvasWidth + 'px';
    canvasCon.style.height = vm.pCanvasHeight + 'px';
    //计算两个canvas原点的x y差值
    let cClientRect = canvas.getBoundingClientRect(),
      pClientRect = pCanvas.getBoundingClientRect();
    vm.originXDiff = pClientRect.left - cClientRect.left;
    vm.originYDiff = pClientRect.top - cClientRect.top;
  }
  //初始化预览的图片
  initPreview() {
    let vm: any = this;
    let pre: any = document.getElementsByClassName("ccui-preview-img")[0];
    if (vm.pCanvasWidth >= vm.pCanvasHeight) {
      vm.previewWidth = 150;
      vm.previewHeight = Number((vm.pCanvasHeight / vm.pCanvasWidth) * 150);
      vm.previewHeight = parseInt(vm.previewHeight);
    } else {
      vm.previewWidth = Number((vm.pCanvasWidth / vm.pCanvasHeight) * 150);
      vm.previewWidth = parseInt(vm.previewWidth);
      vm.previewHeight = 150;
    }
    pre.style.width = vm.previewWidth + "px";
    pre.style.height = vm.previewHeight + "px";
    if (vm.isHead) {
      pre.style.borderRadius = "50%";
    }
  }
  //加载图片
  loadImg() {
    let vm: any = this;
    console.log("进入加载图片");
    if (vm.imgLoading || vm.loadImgQueue.length === 0) {
      return;
    }
    let img = vm.loadImgQueue.shift();
    if (!img) {
      return;
    }
    let image = new Image(),
      onLoad = e => {
        image.removeEventListener("load", onLoad, false);
        image.setAttribute("crossOrigin", "Anonymous");
        vm.img = image;
        vm.imgLoaded = true;
        vm.imgLoading = false;
        vm.originalImgWidth = image.width;
        vm.originalImgHeight = image.height;
        vm.initImg(image.width, image.height);
        vm.loadImg();
      },
      onError = e => {
        image.removeEventListener("error", onError, false);
        vm.img = null;
        vm.imgLoading = false;
        vm.loadImg();
      };
    vm.imgLoading = true;
    vm.imgLoaded = false;
    image.src = vm.imgUrl;
    image.setAttribute("crossOrigin", "Anonymous");
    image.addEventListener("load", onLoad, false);
    image.addEventListener("error", onError, false);
  }
  //初始化图片
  initImg(w, h) {
    let vm = this;
    let eW: any = null,
      eH: any = null,
      maxW: any = vm.clipperSize,
      maxH: any = vm.clipperSize,
      minW: any = vm.pCanvasWidth,
      minH: any = vm.pCanvasHeight;
    //下层图片的位置
    if (minW / minH <= w / h) {
      eW = (w / h) * minH;
      eH = minH;
    } else {
      eW = minW;
      eH = (h / w) * minW;
    }
    //  记录其初始化的宽高，日后的缩放功能以此值为基础
    vm.imgStartWidth = eW;
    vm.imgStartHeight = eH;
    vm.drawCanvas((maxW - eW) / 2, (maxH - eH) / 2, eW, eH);
  }
  //画图
  drawCanvas(x, y, w, h) {
    let vm = this;
    let pCanvas: any = vm.$refs.pCanvas;
    vm.clearCanvas();
    vm.imgX = parseInt(x);
    vm.imgY = parseInt(y);
    vm.imgCurrentWidth = parseInt(w);
    vm.imgCurrentHeight = parseInt(h);
    //更新canvas
    vm.ctx.drawImage(vm.img, x, y, w, h);
    //更新pCanvas，只需要减去两个canvas坐标原点对应的差值即可
    vm.pCtx.drawImage(vm.img, x - vm.originXDiff, y - vm.originYDiff, w, h);
    vm.previewImg = pCanvas.toDataURL();
  }
  clearCanvas() {
    let canvas: any = this.$refs.canvas,
      pCanvas: any = this.$refs.pCanvas;
    canvas.width = canvas.width;
    canvas.height = canvas.height;
    pCanvas.width = pCanvas.width;
    pCanvas.height = pCanvas.height;
  }
  //鼠标滚轮滚动事件
  scollEvent(e) {
    let vm = this;
    let clipperBox: any = document.getElementsByClassName(
      "ccui-clipper-box"
    )[0];
    if (clipperBox.addEventListener) {
      // IE9, Chrome, Safari, Opera
      clipperBox.addEventListener("mousewheel", vm.mouseWheelHandler, false);
      // Firefox
      clipperBox.addEventListener(
        "DOMMouseScroll",
        vm.mouseWheelHandler,
        false
      );
    }
  }
  mouseWheelHandler(e) {
    let vm: any = this;
    let clipperBox: any = document.getElementsByClassName(
      "ccui-clipper-box"
    )[0];
    if (!vm.imgLoaded) {
      return;
    }
    //计算缩放比例
    let detail = e.wheelDelta || e.detail;
    if (detail > 0) {
      //放大
      vm.imgScale += 0.1;
    } else {
      vm.imgScale -= 0.1;
    }
    //限制最小缩放比例是1
    if (vm.imgScale <= 1) {
      vm.imgScale = 1;
    }
    //限制最大缩放比例maxScale
    if (vm.maxScale && vm.imgScale >= vm.maxScale) {
      vm.imgScale = vm.maxScale;
    }
    //滚动时，让图片居中
    let w = vm.imgStartWidth * vm.imgScale;
    let h = vm.imgStartHeight * vm.imgScale;
    vm.drawCanvas((vm.clipperSize - w) / 2, (vm.clipperSize - h) / 2, w, h);
  }
  //放大按钮点击放大
  enlarge() {
    let vm: any = this;
    if (!vm.imgLoaded) {
      return;
    }
    vm.imgScale += 0.2;
    //限制最大缩放比例maxScale
    if (vm.maxScale && vm.imgScale >= vm.maxScale) {
      vm.imgScale = vm.maxScale;
    }
    let w = vm.imgStartWidth * vm.imgScale;
    let h = vm.imgStartHeight * vm.imgScale;
    vm.drawCanvas((vm.clipperSize - w) / 2, (vm.clipperSize - h) / 2, w, h);
  }
  //缩小按钮点击缩小
  narrow() {
    let vm = this;
    if (!vm.imgLoaded) {
      return;
    }
    vm.imgScale -= 0.2;
    //限制最小缩放比例是1
    if (vm.imgScale <= 1) {
      vm.imgScale = 1;
    }
    let w = vm.imgStartWidth * vm.imgScale;
    let h = vm.imgStartHeight * vm.imgScale;
    vm.drawCanvas((vm.clipperSize - w) / 2, (vm.clipperSize - h) / 2, w, h);
  }
  //拖拽
  dragEvent() {
    let vm = this;
    let clipperBox: any = document.getElementsByClassName(
      "ccui-clipper-box"
    )[0];
    clipperBox.onmousedown = function (e) {
      let ev: any = e || window.event;
      let startX: any = ev.clientX;
      let startY: any = ev.clientY;
      let imgStartX: any = vm.imgX;
      let imgStartY: any = vm.imgY;
      clipperBox.onmousemove = function (moveEvent) {
        if (!vm.imgLoaded) {
          return;
        }
        let moveEv: any = moveEvent || window.event;
        let moveX: any = moveEv.clientX - startX; //鼠标移动的x值
        let moveY: any = moveEv.clientY - startY; //鼠标移动的y值
        let x: any = imgStartX + moveX;
        let y: any = imgStartY + moveY;
        let diffX: number = (vm.clipperSize - vm.pCanvasWidth) / 2;
        let diffY: number = (vm.clipperSize - vm.pCanvasHeight) / 2;
        //x,y限制值
        if (x >= diffX) {
          x = diffX;
        } else if (x <= diffX + vm.pCanvasWidth - vm.imgCurrentWidth) {
          x = diffX + vm.pCanvasWidth - vm.imgCurrentWidth;
        }
        if (y >= diffY) {
          y = diffY;
        } else if (y <= diffY + vm.pCanvasHeight - vm.imgCurrentHeight) {
          y = diffY + vm.pCanvasHeight - vm.imgCurrentHeight;
        }
        vm.drawCanvas(x, y, vm.imgCurrentWidth, vm.imgCurrentHeight);
      };
      window.onmouseup = function () {
        clipperBox.onmousemove = false;
        clipperBox.onmouseup = false;
        //解绑移动事件
        return false;
      };
      return false;
    };
  }
  //关闭
  close() {
    document.documentElement.style.overflowY = this.overflowY;
  }
  //确定
  confirm() {
    let vm: any = this;
    let imgData = vm.previewImg;
    //生成canvas
    let canvas = document.createElement('canvas');
    let laseCtx = canvas.getContext('2d');
    if (vm.width) {
      canvas.width = vm.width;
      canvas.height = vm.height;
    } else {
      //原图的宽（vm.originalImgWidth）:生成canvas的宽 = 现在图片的宽（vm.imgStartWidth * vm.imgScale）:裁切框的宽 （vm.pCanvasWidth）
      canvas.width = vm.originalImgWidth * vm.pCanvasWidth / (vm.imgStartWidth * vm.imgScale);
      canvas.height = vm.originalImgHeight * vm.pCanvasHeight / (vm.imgStartHeight * vm.imgScale);
    }
    let bili: any = canvas.width / vm.pCanvasWidth;
    laseCtx.drawImage(vm.img, (vm.imgX - vm.originXDiff) * bili, (vm.imgY - vm.originYDiff) * bili, vm.imgCurrentWidth * bili, vm.imgCurrentHeight * bili);
    imgData = canvas.toDataURL();
    //生成canvas图片
    vm.close();
    vm.$emit('confirm', imgData);
  }
  //取消
  cancel() {
    this.close();
    this.$emit("cancel");
  }
}
